//@author A0088310L
#ifndef EXECUTOR_H_
#define EXECUTOR_H_

//@author A0088310L
#define TAB				"\t"
#define EMPTY_STRING	""
#define ONE_HOUR		100
#define INITIAL			"initial"
#define FORMATTED		"formatted"
#define ERR			"error"

#include "Task.h"
#include "Validator.h"
#include "Storage.h"
#include "UserInterface.h"
#include "Exception.h"
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <fstream>
#include <assert.h>

using namespace std;

class Executor{
public:
	// These are the possible command types
	static enum COMMAND_TYPE {
		ADD, DELET, SHOW, SEARCH, CLEAR, DONE, UNDONE, EDIT, POSTPONE, UNDO, HELP, EXIT, INVALID
	};	
	static enum KEYWORD_TYPE {
		NAME, DATE, STARTS, ENDS, DETAIL, IMPT, UNIMPT, REPEAT
	};	
	static enum SHOW_TYPE {
		SHOW_IMPT, SHOW_DONE, SHOW_UNDONE, SHOW_DETAIL, SHOW_TIME, SHOW_FLOATING, SHOW_ALL, SHOW_DATE
	};

	static vector<Task*> taskList;
	static string display;

	void loadVect();
	void saveCommand(string command);
	void storeToFile();

	COMMAND_TYPE determineCommandType(string commandTypeString_lowered);
	KEYWORD_TYPE determineKeywordType(string keywordTypeString);
	SHOW_TYPE determineShowType(string showTypeString_lowered);
	
	string toLowerCase(string word);
	
	string getFirstWord(string inputLine);
	string extractFirstWord(string &inputLine);
	
	string executeCommand(string inputLine);
	
	string executeAdd(string inputLine);
	string getNewTasksInfo(int prev_taskListSize, int curr_taskListSize);
	void addToTaskList(Task* t);
	string makeTask(string inputLine, Task * &t);
	string makeString(int time);
	string makeProperTimings(Task* &t);
	string makeTaskName(string &inputline, Task* &t);
	string makeTaskDate(string &inputline, Task* &t);
	string makeTaskStartTime(string &inputline, Task* &t);
	string makeTaskEndTime(string &inputline, Task* &t);
	string makeTaskImpt(Task* &t);
	string makeTaskDetail(string &inputline, Task* &t);
	string makeTaskRepeat(string &inputLine, Task* t);
	void copyTask(Task* &t_temp, Task* t);
	string basicTaskInfo(int taskIndex);
	string allTaskInfo(int taskIndex);

	string executeDelete(string inputLine);
	int makeInt(string taskNum_str);
	
	string executeShow(string inputLine);
	string showAll();
	string showImpt();
	string showDone();
	string showUndone();
	string showDetail(string inputLine);
	string showTime(string inputLine);
	string showDate(string date);
	string showFloating();

	string executeSearch(string inputLine);

	string executeClear(string inputLine);
	string clearAll();
	string clearTasksOnDate(string date);
	
	string executeDone(string inputLine);
	string executeUndone(string inputLine);

	string executeEdit(string inputLine);
	string editName(string inputLine, int vectIndex);
	string makeTaskNotImpt(Task* &t);
	string makeTaskNotDone(Task* &t);
	string editDetail(string inputLine, int vectIndex);

	string executePostpone(string inputLine);
	string postponeAllTask(string inputLine);
	string postponeSingleTask(string taskNum_str, string inputLine);

	string executeUndo();

	string executeHelp();

	string executeExit();

	//For UserInterface to retrieve data from taskList in Executor
	bool isRetrievedTaskList(string date, vector<int> &fileIndex, vector<string> &subject, vector<bool> &done);
	bool isRetrievedFloatingTasks(vector<int> &fileIndex, vector<string> &subject);
	bool isRetrievedPendingTasks(vector<int> &fileIndex, vector<string> &subject); //show pending task from tom only
};

#endif
